﻿/**
 * AlternativaTemplate
 * Alternativa3D 7.7.0 基本模板
 * @ by ssnangua
 *
 */
package artin.A3D7.template 
{
	import alternativa.engine3d.containers.BSPContainer;
	import alternativa.engine3d.containers.ConflictContainer;
	import alternativa.engine3d.containers.DistanceSortContainer;
	import alternativa.engine3d.containers.KDContainer;
	import alternativa.engine3d.containers.LODContainer;
	import alternativa.engine3d.controllers.SimpleObjectController;
	import alternativa.engine3d.core.Camera3D;
	import alternativa.engine3d.core.Object3DContainer;
	import alternativa.engine3d.core.View;
	
	import flash.display.DisplayObject;
	import flash.display.DisplayObjectContainer;
	import flash.display.Sprite;
	import flash.display.StageAlign;
	import flash.display.StageQuality;
	import flash.display.StageScaleMode;
	import flash.events.Event;// 事件


	public class AlternativaTemplate extends Sprite
	{
		/**
		 * ConflictContainer
		 * 能很好地对子对象进行排序
		 */
		public static const CONFLICT:String = 'conflict';

		/**
		 * BSPContainer
		 * 以BSP（二进制空间分割技术）树对子对象进行排序
		 */
		public static const BSP:String = 'bsp';

		/**
		 * DistanceSortContainer
		 * 以子对象和摄像头的Z轴平均值对子对象进行排序
		 */
		public static const ZSORT:String = 'zsort';

		/**
		 * KDContainer
		 * 以KD树对子对象进行排序
		 */
		public static const KD:String = 'kd';

		/**
		 * LODContainer
		 * 按距离对子对象进行排序
		 */
		public static const LOD:String = 'lod';

		/**
		 * Object3DContainer
		 * 三维对象实例的容器
		 */
		public var container:Object3DContainer;

		/**
		 * 视窗实例
		 */
		public var view:View;

		/**
		 * 摄像头实例
		 */
		public var camera:Camera3D;

		/**
		 * 摄像头控制器
		 */
		public var cameraController:SimpleObjectController;

		private var _mc:DisplayObjectContainer;
		private var _containerType:String;
		private var _viewWidth:int;
		private var _viewHeight:int;
		private var _scaleToStage:Boolean;

		/**
		 * AlternativaTemplate
		 * @param    mc
		 * @param    containerType
		 * @param    viewWidth
		 * @param    viewHeight
		 * @param    scaleToStage
		 * @param    showLogo 
		 */
		public function AlternativaTemplate(mc:DisplayObjectContainer,containerType:String=CONFLICT,viewWidth:int=640, viewHeight:int=480, scaleToStage:Boolean = true,showLogo:Boolean=false)
			
		//public function AlternativaTemplate(mc:DisplayObjectContainer,containerType:String=CONFLICT,viewWidth:int=640, viewHeight:int=480, scaleToStage:Boolean = true,showLogo:Boolean=false)
		{
			/**
			 * 父容器
			 */
			_mc = mc;
			_mc.addChild(this);
			
			/**
			 * 3D容器类型
			 */
			_containerType = containerType;
			
			/**
			 * 视窗大小
			 */
			_viewWidth = viewWidth;
			_viewHeight = viewHeight;
			
			/**
			 * 舞台设置
			 */
			_scaleToStage = scaleToStage;
			
			/**
			 * 初始化
			 */
			if (stage) init();
			else addEventListener(Event.ADDED_TO_STAGE, init);
			/**
			 * 显示隐藏Logo
			 */
			if(showLogo) view.showLogo() else view.hideLogo();
		}

		/**
		 * 在初始化事件中执行
		 * 通过重写该事件实现其它初始化
		 */
		protected function atInit():void {}

		/**
		 * 在渲染事件中执行（Event.ENTER_FRAME）
		 * 在摄像头渲染前执行
		 */
		protected function atPreRender():void {}
		private var _onPreRender:Function = function():void{};
		public function get onPreRender():Function
		{
			return _onPreRender;
		}
		public function set onPreRender(value:Function):void
		{
			_onPreRender = value;
		}

		/**
		 * 在渲染事件中执行（Event.ENTER_FRAME）
		 * 在摄像头渲染后执行
		 */
		protected function atPostRender():void {}
		private var _onPostRender:Function = function():void{};
		public function get onPostRender():Function
		{
			return _onPostRender;
		}
		public function set onPostRender(value:Function):void
		{
			_onPostRender = value;
		}


		/**
		 * 开始渲染
		 */
		public function startRendering():void
		{
			addEventListener(Event.ENTER_FRAME, onRenderTick);
		}

		/**
		 * 停止渲染
		 */
		public function stopRendering():void
		{
			removeEventListener(Event.ENTER_FRAME, onRenderTick);
		}

		/**
		 * 只需渲染一次时执行
		 */
		public function singleRender():void
		{
			onRenderTick();
		}

		/**
		 * 初始化
		 */
		private function init(e:Event = null):void
		{
			removeEventListener(Event.ADDED_TO_STAGE, init);
			
			/**
			 * 舞台设置
			 */
			stage.scaleMode = StageScaleMode.NO_SCALE;
			stage.align = StageAlign.TOP_LEFT;
			stage.quality = StageQuality.HIGH;
			
			/**
			 * 创建一个根容器对象
			 */
			if (_containerType == CONFLICT)
			{
				container = new ConflictContainer();
			}
			else if (_containerType == BSP)
			{
				container = new BSPContainer();
			}
			else if (_containerType == ZSORT)
			{
				container = new DistanceSortContainer();
			}
			else if (_containerType == KD)
			{
				container = new KDContainer();
			}
			else if (_containerType == LOD)
			{
				container = new LODContainer();
			}

			/**
			 * 创建视窗
			 */
			view = new View(stage.stageWidth,stage.stageHeight);
			_mc.addChild(view);

			/**
			 * 创建一个摄像头
			 */
			camera = new Camera3D();
			camera.view = view;
			camera.x = 0;
			camera.y = -500;
			camera.z = 0;
			container.addChild(camera);

			/**
			 * 摄像头控制器
			 */
			cameraController = new SimpleObjectController(stage,camera,100);
			cameraController.mouseSensitivity = 0;
			cameraController.unbindAll();
			cameraController.lookAtXYZ(0, 0, 0);
			
			/**
			 * 视窗大小
			 */
			onResize();
			stage.addEventListener(Event.RESIZE, onResize);
			
			/**
			 * 其它初始化
			 */
			atInit();
		}

		/**
		 * 视窗大小
		 */
		private function onResize(e:Event = null):void
		{
			if (_scaleToStage)
			{
				view.width = stage.stageWidth;
				view.height = stage.stageHeight;
			}
			else
			{
				view.width = _viewWidth;
				view.height = _viewHeight;
			}
		}

		/**
		 * 渲染
		 */
		private function onRenderTick(e:Event = null):void
		{
			atPreRender();
			_onPreRender();

			cameraController.update();
			camera.render();

			atPostRender();
			_onPostRender();
		}


	}

}